package com.caidan.search.service.impl;

import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.MD5;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.caidan.common.constants.SystemConstants;
import com.caidan.common.result.Result;
import com.caidan.common.result.ResultCodeEnum;
import com.caidan.common.util.AuthContextHolder;
import com.caidan.common.util.ConvertBeanUtils;
import com.caidan.framework.redis.key.MegProviderCacheKeyBuilder;
import com.caidan.framework.redis.key.UserProviderCacheKeyBuilder;
import com.caidan.model.domain.user.User;
import com.caidan.model.dto.user.UserLoginDTO;
import com.caidan.model.dto.user.UserRegisterDTO;
import com.caidan.model.dto.user.UserUpdateDTO;
import com.caidan.model.vo.user.UserVo;
import com.caidan.search.mapper.UserMapper;
import com.caidan.search.service.UserService;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * @项目名 CaiDanSearchSystem
 * @描述 用户接口服务层实现
 * @作者 小菜蛋
 * @时间 2024/12/1 19:55
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Resource
    private StringRedisTemplate stringRedisTemplate;
    @Resource
    private MegProviderCacheKeyBuilder megProviderCacheKeyBuilder;
    @Resource
    private UserProviderCacheKeyBuilder userProviderCacheKeyBuilder;
    private static final String PASSWORD_CHECK_STATUS = "T";
    @Resource
    private UserMapper userMapper;

    /**
     * 校验验证码
     * @param phoneNumber 手机号
     * @param code 验证码
     * @return 是否验证成功
     */
    private boolean validateCode(String phoneNumber, String code) {
        String key = megProviderCacheKeyBuilder.buildUserInfoKey(phoneNumber);
        String redisCode = stringRedisTemplate.opsForValue().get(key);
        if (!code.equals(redisCode)) {
            log.warn("验证码错误，手机号：{}", phoneNumber);
            return false;
        }
        // 删除验证码信息
        stringRedisTemplate.delete(key);
        return true;
    }

    /**
     * 校验密码
     * @param userLoginDTO 登录请求DTO
     * @return 是否验证成功
     */
    private String validatePassword(UserLoginDTO userLoginDTO, User user) {

        if (!userLoginDTO.getPassword().equals(user.getPassword())) {
            log.warn("密码错误，手机号：{}", userLoginDTO.getPhoneNumber());
            return ResultCodeEnum.PASSWORD_ERROR.getMessage();
        }
        return PASSWORD_CHECK_STATUS;
    }

    @Override
    public Result<String> userLogin(UserLoginDTO userLoginDTO) {
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, userLoginDTO.getPhoneNumber()));
        if (null == user) {
            return Result.ok(ResultCodeEnum.USER_NOT_EXISTED.getMessage());
        }
        // 校验验证码或密码
        if (!StrUtil.isBlank(userLoginDTO.getCode())) {
            if (!validateCode(userLoginDTO.getPhoneNumber(), userLoginDTO.getCode())) {
                return Result.fail(ResultCodeEnum.PHONE_CODE_ERROR.getMessage());
            }
        } else if (!StrUtil.isBlank(userLoginDTO.getPassword())) {
//            USER_NOT_EXISTED
            String res = this.validatePassword(userLoginDTO, user);
            if (!res.equals(PASSWORD_CHECK_STATUS)) {
                return Result.fail(res);
            }
        } else {
            return Result.fail(ResultCodeEnum.ARGUMENT_VALID_ERROR.getMessage());
        }
        String sign = this.createSign(userLoginDTO.getPhoneNumber());
        // 返回登录成功结果
        log.info("用户 {} 登录成功，生成的登录 token: {}", userLoginDTO.getPhoneNumber(), sign);
        this.saveUserMessage(sign, user.getId());
        return Result.ok(sign);
    }

    private void saveUserMessage(String token, Long id) {
        String key = userProviderCacheKeyBuilder.buildUserMessageToken(token);
//        储存用户信息
        stringRedisTemplate.opsForValue().set(key, id.toString(), 30, TimeUnit.DAYS);
    }

    private String createSign(String phoneNumber) {
        // 创建登录签名
        String sign = UUID.randomUUID().toString().replace("-", "");
        String key = userProviderCacheKeyBuilder.buildUserLoginTokenKey(phoneNumber);
        // 设置登录 token，过期时间为30天
        stringRedisTemplate.opsForValue().set(key, sign, SystemConstants.USER_LOGIN_TIME, TimeUnit.DAYS);
        return sign;
    }

    @Override
    public Result<String> userRegister(UserRegisterDTO userRegisterDTO) {
//        校验用户是否存在
        User user = userMapper.selectOne(new LambdaQueryWrapper<User>().eq(User::getPhoneNumber, userRegisterDTO.getPhoneNumber()));
        if (null != user) {
            return Result.fail(ResultCodeEnum.USER_EXISTED.getMessage());
        }
//        校验验证码是否正确
        String key = megProviderCacheKeyBuilder.buildUserInfoKey(userRegisterDTO.getPhoneNumber());
        if (null == key || !this.validateCode(userRegisterDTO.getPhoneNumber(), userRegisterDTO.getCode())) {
            return Result.fail(ResultCodeEnum.PHONE_CODE_ERROR.getMessage());
        }
        User userStore = new User();
        userStore.setPhoneNumber(userRegisterDTO.getPhoneNumber());
        userStore.setCreatedAt(new Date());
        userStore.setUpdatedAt(new Date());
        userStore.setUsername("搜索鸭-" + UUID.randomUUID().toString().replace("-", "").substring(1, 9));
        userStore.setProfilePictureUrl("http://124.71.148.150:9001/api/v1/buckets/hamos/objects/download?preview=true&prefix=5d5f43c0b2364119b6b6599cb981ed63.jpg&version_id=null");
        userStore.setPassword(MD5.create().digestHex(UUID.randomUUID().toString().replace("-", "").substring(1, 9)));
        userStore.setBackgroundImage("http://124.71.148.150:9001/api/v1/buckets/cdatguiguts/objects/download?preview=true&prefix=fee80f9084444c44b847622e1ba5760e&version_id=null");
        int insert = userMapper.insert(userStore);
        if (insert <= 0) {
            return Result.fail(ResultCodeEnum.FAIL.getMessage());
        }
        //        生成sign
        String sign = this.createSign(userRegisterDTO.getPhoneNumber());
        log.info("用户 {} 注册成功，生成的登录 token: {}", userRegisterDTO.getPhoneNumber(), sign);
        this.saveUserMessage(sign, userStore.getId());
        return Result.ok(sign);
    }

    @Override
    public Result<UserVo> getUserVoMessage(Long id) {
        User user = userMapper.selectById(id);
        if (null == user) {
            log.info("用户信息查询 结果用户信息为空");
            return Result.fail();
        }
        UserVo userVo = ConvertBeanUtils.convert(user, UserVo.class);
        log.info("用户 {} 查询成功", user.getId());
        return Result.ok(userVo);
    }

    @Override
    public Result updateUserMessage(Long userId, UserUpdateDTO userUpdateDTO) {
        User user = new User();
        user.setId(userId);
        if (!StrUtil.isBlank(userUpdateDTO.getCode())) {
            String key = megProviderCacheKeyBuilder.buildUserInfoKey(userUpdateDTO.getPhoneNumber());
            String redisCode = stringRedisTemplate.opsForValue().get(key);
            if (StrUtil.isBlank(redisCode)) {
                return Result.fail(ResultCodeEnum.FAIL.getMessage());
            }
            if (!redisCode.equals(userUpdateDTO.getCode())) {
                return Result.fail(ResultCodeEnum.PHONE_CODE_ERROR.getMessage());
            }
            user.setPassword(userUpdateDTO.getPassword());
        } else {
            user.setProfilePictureUrl(userUpdateDTO.getProfilePictureUrl());
        }
        user.setUpdatedAt(new Date());
        try {
            int res = userMapper.updateById(user);
            if (res <= 0) {
                throw new Exception("用户更新失败");
            }
            return Result.ok();
        } catch (Exception e) {
            log.error("用户{}信息更新失败，错误信息{}", user.getId(), e.getMessage());
            return Result.fail();
        }
    }

    @Override
    public Result deleteUserMessage(Long id) {
        int res = userMapper.deleteById(id);
        if (res <= 0) {
            return Result.fail(ResultCodeEnum.FAIL.getMessage());
        }
        return Result.ok();
    }

    @Override
    public Result updateSystemImg(String url) {
        Long userId = AuthContextHolder.getUserId();
        if(userId == null){
            return Result.fail(ResultCodeEnum.ILLEGAL_REQUEST.getMessage());
        }
        User user = new User();
        user.setId(userId);
        user.setBackgroundImage(url);
        int res = userMapper.updateById(user);
        if (res <= 0) {
            return Result.fail(ResultCodeEnum.SERVICE_ERROR.getMessage());
        }
        return Result.ok();
    }
}
